import tkinter as tk
from tkinter import ttk, messagebox
import math
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib

# 设置matplotlib使用支持中文的字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

class GeometryCalculator:
    def __init__(self, root):
        self.root = root
        self.root.title("几何图形计算器")
        self.root.geometry("800x600")
        self.root.resizable(True, True)
        
        # 创建主框架
        main_frame = ttk.Frame(root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置网格权重
        root.columnconfigure(0, weight=1)
        root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.rowconfigure(1, weight=1)
        
        # 创建左侧输入框架
        input_frame = ttk.LabelFrame(main_frame, text="图形参数", padding="10")
        input_frame.grid(row=0, column=0, rowspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(0, 10))
        
        # 图形选择
        ttk.Label(input_frame, text="选择图形:").grid(row=0, column=0, sticky=tk.W, pady=(0, 10))
        self.shape_var = tk.StringVar(value="圆形")
        shape_combo = ttk.Combobox(input_frame, textvariable=self.shape_var, 
                                  values=["圆形", "矩形", "直角三角形", "等边三角形", "梯形", "菱形"])
        shape_combo.grid(row=0, column=1, sticky=(tk.W, tk.E), pady=(0, 10))
        shape_combo.bind('<<ComboboxSelected>>', self.on_shape_change)
        
        # 参数输入区域
        self.param_frame = ttk.Frame(input_frame)
        self.param_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 计算按钮
        ttk.Button(input_frame, text="计算", command=self.calculate).grid(row=2, column=0, columnspan=2, pady=10)
        
        # 创建右侧结果显示框架
        result_frame = ttk.LabelFrame(main_frame, text="计算结果", padding="10")
        result_frame.grid(row=0, column=1, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        result_frame.columnconfigure(0, weight=1)
        result_frame.rowconfigure(1, weight=1)
        
        # 结果显示文本
        self.result_text = tk.Text(result_frame, height=8, width=40)
        self.result_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 创建滚动条
        scrollbar = ttk.Scrollbar(result_frame, orient="vertical", command=self.result_text.yview)
        scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
        self.result_text.configure(yscrollcommand=scrollbar.set)
        
        # 创建图形显示框架
        plot_frame = ttk.LabelFrame(main_frame, text="图形显示", padding="10")
        plot_frame.grid(row=1, column=1, sticky=(tk.W, tk.E, tk.N, tk.S))
        plot_frame.columnconfigure(0, weight=1)
        plot_frame.rowconfigure(0, weight=1)
        
        # 创建matplotlib图形
        self.fig = Figure(figsize=(5, 4), dpi=100)
        self.ax = self.fig.add_subplot(111)
        self.canvas = FigureCanvasTkAgg(self.fig, plot_frame)
        self.canvas.get_tk_widget().grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 初始化参数输入
        self.param_entries = {}
        self.on_shape_change()
        
    def on_shape_change(self, event=None):
        # 清除参数输入区域
        for widget in self.param_frame.winfo_children():
            widget.destroy()
        
        shape = self.shape_var.get()
        self.param_entries = {}
        
        if shape == "圆形":
            self.create_param_input("半径:", 0)
        elif shape == "矩形":
            self.create_param_input("长度:", 0)
            self.create_param_input("宽度:", 1)
        elif shape == "直角三角形":
            self.create_param_input("直角边a:", 0)
            self.create_param_input("直角边b:", 1)
        elif shape == "等边三角形":
            self.create_param_input("边长:", 0)
        elif shape == "梯形":
            self.create_param_input("上底:", 0)
            self.create_param_input("下底:", 1)
            self.create_param_input("高:", 2)
            self.create_param_input("左边长:", 3)
            self.create_param_input("右边长:", 4)
        elif shape == "菱形":
            self.create_param_input("对角线1:", 0)
            self.create_param_input("对角线2:", 1)
    
    def create_param_input(self, label, row):
        ttk.Label(self.param_frame, text=label).grid(row=row, column=0, sticky=tk.W, pady=2)
        entry = ttk.Entry(self.param_frame)
        entry.grid(row=row, column=1, sticky=(tk.W, tk.E), pady=2)
        self.param_entries[label] = entry
    
    def calculate(self):
        try:
            shape = self.shape_var.get()
            params = {}
            
            # 获取参数值
            for label, entry in self.param_entries.items():
                value = entry.get().strip()
                if not value:
                    messagebox.showerror("输入错误", f"请填写{label}")
                    return
                try:
                    params[label] = float(value)
                    # 检查参数是否为正数
                    if params[label] <= 0:
                        messagebox.showerror("输入错误", f"{label}必须大于0")
                        return
                except ValueError:
                    messagebox.showerror("输入错误", f"{label}必须是数字")
                    return
            
            # 根据图形类型计算
            if shape == "圆形":
                radius = params["半径:"]
                area, perimeter = self.calculate_circle(radius)
                self.plot_circle(radius)
            elif shape == "矩形":
                length = params["长度:"]
                width = params["宽度:"]
                area, perimeter = self.calculate_rectangle(length, width)
                self.plot_rectangle(length, width)
            elif shape == "直角三角形":
                a = params["直角边a:"]
                b = params["直角边b:"]
                area, perimeter = self.calculate_right_triangle(a, b)
                self.plot_right_triangle(a, b)
            elif shape == "等边三角形":
                side = params["边长:"]
                area, perimeter = self.calculate_equilateral_triangle(side)
                self.plot_equilateral_triangle(side)
            elif shape == "梯形":
                top = params["上底:"]
                bottom = params["下底:"]
                height = params["高:"]
                left = params["左边长:"]
                right = params["右边长:"]
                area, perimeter = self.calculate_trapezoid(top, bottom, height, left, right)
                self.plot_trapezoid(top, bottom, height)
            elif shape == "菱形":
                d1 = params["对角线1:"]
                d2 = params["对角线2:"]
                area, perimeter = self.calculate_rhombus(d1, d2)
                self.plot_rhombus(d1, d2)
            
            # 显示结果
            result = f"图形: {shape}\n"
            result += f"面积: {area:.4f}\n"
            result += f"周长: {perimeter:.4f}\n"
            
            # 添加公式说明
            result += "\n计算公式:\n"
            if shape == "圆形":
                result += f"面积 = π × 半径² = {math.pi:.4f} × {params['半径:']}²\n"
                result += f"周长 = 2 × π × 半径 = 2 × {math.pi:.4f} × {params['半径:']}"
            elif shape == "矩形":
                result += f"面积 = 长 × 宽 = {params['长度:']} × {params['宽度:']}\n"
                result += f"周长 = 2 × (长 + 宽) = 2 × ({params['长度:']} + {params['宽度:']})"
            elif shape == "直角三角形":
                c = math.sqrt(params['直角边a:']**2 + params['直角边b:']**2)
                result += f"面积 = 1/2 × 直角边a × 直角边b = 1/2 × {params['直角边a:']} × {params['直角边b:']}\n"
                result += f"周长 = 直角边a + 直角边b + 斜边 = {params['直角边a:']} + {params['直角边b:']} + {c:.4f}"
            elif shape == "等边三角形":
                result += f"面积 = (√3/4) × 边长² = ({math.sqrt(3):.4f}/4) × {params['边长:']}²\n"
                result += f"周长 = 3 × 边长 = 3 × {params['边长:']}"
            elif shape == "梯形":
                result += f"面积 = 1/2 × (上底 + 下底) × 高 = 1/2 × ({params['上底:']} + {params['下底:']}) × {params['高:']}\n"
                result += f"周长 = 上底 + 下底 + 左边长 + 右边长 = {params['上底:']} + {params['下底:']} + {params['左边长:']} + {params['右边长:']}"
            elif shape == "菱形":
                side = math.sqrt((params['对角线1:']/2)**2 + (params['对角线2:']/2)**2)
                result += f"面积 = 1/2 × 对角线1 × 对角线2 = 1/2 × {params['对角线1:']} × {params['对角线2:']}\n"
                result += f"周长 = 4 × 边长 = 4 × {side:.4f}"
            
            self.result_text.delete(1.0, tk.END)
            self.result_text.insert(tk.END, result)
            
        except Exception as e:
            messagebox.showerror("计算错误", f"发生错误: {str(e)}")
    
    # 圆形计算和绘制
    def calculate_circle(self, radius):
        area = math.pi * radius * radius
        perimeter = 2 * math.pi * radius
        return area, perimeter
    
    def plot_circle(self, radius):
        self.ax.clear()
        circle = plt.Circle((0, 0), radius, fill=False, edgecolor='blue', linewidth=2)
        self.ax.add_patch(circle)
        self.ax.set_xlim(-radius-1, radius+1)
        self.ax.set_ylim(-radius-1, radius+1)
        self.ax.set_aspect('equal')
        self.ax.set_title("圆形", fontsize=14)
        self.ax.grid(True, linestyle='--', alpha=0.7)
        self.canvas.draw()
    
    # 矩形计算和绘制
    def calculate_rectangle(self, length, width):
        area = length * width
        perimeter = 2 * (length + width)
        return area, perimeter
    
    def plot_rectangle(self, length, width):
        self.ax.clear()
        rectangle = plt.Rectangle((0, 0), length, width, fill=False, edgecolor='red', linewidth=2)
        self.ax.add_patch(rectangle)
        self.ax.set_xlim(-1, length+1)
        self.ax.set_ylim(-1, width+1)
        self.ax.set_aspect('equal')
        self.ax.set_title("矩形", fontsize=14)
        self.ax.grid(True, linestyle='--', alpha=0.7)
        self.canvas.draw()
    
    # 直角三角形计算和绘制
    def calculate_right_triangle(self, a, b):
        area = 0.5 * a * b
        c = math.sqrt(a*a + b*b)
        perimeter = a + b + c
        return area, perimeter
    
    def plot_right_triangle(self, a, b):
        self.ax.clear()
        triangle = plt.Polygon([[0, 0], [a, 0], [0, b]], fill=False, edgecolor='green', linewidth=2)
        self.ax.add_patch(triangle)
        self.ax.set_xlim(-1, max(a, b)+1)
        self.ax.set_ylim(-1, max(a, b)+1)
        self.ax.set_aspect('equal')
        self.ax.set_title("直角三角形", fontsize=14)
        self.ax.grid(True, linestyle='--', alpha=0.7)
        self.canvas.draw()
    
    # 等边三角形计算和绘制
    def calculate_equilateral_triangle(self, side):
        area = (math.sqrt(3) / 4) * side * side
        perimeter = 3 * side
        return area, perimeter
    
    def plot_equilateral_triangle(self, side):
        self.ax.clear()
        height = math.sqrt(3) / 2 * side
        triangle = plt.Polygon([[0, 0], [side, 0], [side/2, height]], fill=False, edgecolor='orange', linewidth=2)
        self.ax.add_patch(triangle)
        self.ax.set_xlim(-1, side+1)
        self.ax.set_ylim(-1, height+1)
        self.ax.set_aspect('equal')
        self.ax.set_title("等边三角形", fontsize=14)
        self.ax.grid(True, linestyle='--', alpha=0.7)
        self.canvas.draw()
    
    # 梯形计算和绘制
    def calculate_trapezoid(self, top, bottom, height, left, right):
        area = 0.5 * (top + bottom) * height
        perimeter = top + bottom + left + right
        return area, perimeter
    
    def plot_trapezoid(self, top, bottom, height):
        self.ax.clear()
        # 计算梯形顶点
        offset = (bottom - top) / 2
        trapezoid = plt.Polygon([
            [0, 0], 
            [bottom, 0], 
            [bottom - offset, height], 
            [offset, height]
        ], fill=False, edgecolor='purple', linewidth=2)
        self.ax.add_patch(trapezoid)
        self.ax.set_xlim(-1, bottom+1)
        self.ax.set_ylim(-1, height+1)
        self.ax.set_aspect('equal')
        self.ax.set_title("梯形", fontsize=14)
        self.ax.grid(True, linestyle='--', alpha=0.7)
        self.canvas.draw()
    
    # 菱形计算和绘制
    def calculate_rhombus(self, d1, d2):
        area = 0.5 * d1 * d2
        side = math.sqrt((d1/2)**2 + (d2/2)**2)
        perimeter = 4 * side
        return area, perimeter
    
    def plot_rhombus(self, d1, d2):
        self.ax.clear()
        rhombus = plt.Polygon([
            [0, d2/2], 
            [d1/2, 0], 
            [0, -d2/2], 
            [-d1/2, 0]
        ], fill=False, edgecolor='brown', linewidth=2)
        self.ax.add_patch(rhombus)
        self.ax.set_xlim(-d1/2-1, d1/2+1)
        self.ax.set_ylim(-d2/2-1, d2/2+1)
        self.ax.set_aspect('equal')
        self.ax.set_title("菱形", fontsize=14)
        self.ax.grid(True, linestyle='--', alpha=0.7)
        self.canvas.draw()

if __name__ == "__main__":
    root = tk.Tk()
    app = GeometryCalculator(root)
    root.mainloop()
